
# -*- coding: UTF-8 -*-
import datetime
import time

from lj_tool import tool_id

max_expiration_seconds = 60 * 60 * 24 * 365

cache_dict = {}
cache_expiration_time = {}


def lj_wrapper_cache(key, expiration_seconds=None, expiration_milliseconds=None, c_args=None):
    if not expiration_milliseconds:
        expiration_milliseconds = 60 * 10 * 1000
    if expiration_seconds:
        expiration_milliseconds = expiration_seconds * 1000

    def decorator(func):
        def wrapper(*args, **kwargs):
            # print(
            #     f"缓存key[{tool_id.gen_un_key(key, *args, **kwargs)}][{cache_expiration_time}]")
            return lj_cache(gen_key(key, c_args, *args, **kwargs), lambda: func(*args, **kwargs), gen_expiration_milliseconds(expiration_milliseconds))
        return wrapper
    return decorator


def lj_cache(key, fun=None, expiration_time=None):
    """缓存函数 - 封装后"""
    if is_expir(key):
        val = fun()
        setVal(key, val, expiration_time)
    return getVal(key)


def setVal(key, val, expiration_time=None):
    """进行缓存"""
    cache_dict[key] = val
    cache_expiration_time[key] = gen_expiration_time(expiration_time)


def gen_expiration_milliseconds(expiration_milliseconds):
    """过期时间生成 - 毫秒"""
    return datetime.datetime.now() + datetime.timedelta(milliseconds=expiration_milliseconds)


def gen_expiration_time(expiration_time):
    """过期时间生成"""
    return expiration_time or datetime.datetime.now() + datetime.timedelta(hours=8)


def getVal(key):
    # 是否过期
    is_expir(key)
    # 字典获取值
    return cache_dict.get(key)


def is_expir(key):
    """是否过期"""
    extTime = cache_expiration_time.get(key)
    # 判断存在过期时间并且已过期的话执行删除动作
    if not extTime or datetime.datetime.now() > extTime:
        # 删除过期时间存储
        if cache_expiration_time.get(key):
            del cache_expiration_time[key]
        # 删除过期值存储
        if cache_dict.get(key):
            del cache_dict[key]
        return True
    return False


def gen_key(key, c_args=None, *args, **kwargs):
    """唯一标识生成"""
    uk_args = args
    if c_args:
        # 如果传入有过滤条件则执行条件过滤
        uk_args = [args[i] for i in c_args]
    return tool_id.gen_un_key(key, *uk_args, **kwargs)


def ref_expiration_time(key, mill):
    """节流辅助函数"""
    last_executed = cache_expiration_time.get(key)

    current_time = time.time()
    if not last_executed or current_time > last_executed:
        cache_expiration_time[key] = time.time() + mill
        return True
    return False


def throttle(key, wait=10, c_args=None):
    """节流函数"""
    def decorator(fn):
        def throttled(*args, **kwargs):
            if ref_expiration_time(gen_key(key, c_args, *args, **kwargs), wait):
                return fn(*args, **kwargs)
        return throttled
    return decorator


def throttle_async(key, wait=10, c_args=None):
    """节流函数"""
    def decorator(fn):
        async def throttled(*args, **kwargs):
            if ref_expiration_time(gen_key(key, c_args, *args, **kwargs), wait):
                return await fn(*args, **kwargs)
        return throttled
    return decorator
